const Redis = require('ioredis');
const config = require('../config');

const redis = new Redis({
    host: config.redis.host,
    port: config.redis.port,
    password: config.redis.password,
    db: config.redis.db
});

const redisUtils = {
    /**
     * 从左侧插入列表（先进后出，类似栈）
     * @param {string} key Redis键
     * @param {any} value 要插入的值
     */
    async lpush(key, value) {
        try {
            return await redis.lpush(key, JSON.stringify(value));
        } catch (error) {
            console.error('Redis lpush error:', error);
            throw error;
        }
    },

    /**
     * 从右侧插入列表（先进先出，类似队列）
     * @param {string} key Redis键
     * @param {any} value 要插入的值
     */
    async rpush(key, value) {
        try {
            return await redis.rpush(key, JSON.stringify(value));
        } catch (error) {
            console.error('Redis rpush error:', error);
            throw error;
        }
    },

    /**
     * 在指定元素之前/之后插入
     * @param {string} key Redis键
     * @param {string} pivot 参考元素
     * @param {any} value 要插入的值
     * @param {boolean} before 是否在之前插入
     */
    async linsert(key, pivot, value, before = true) {
        try {
            return await redis.linsert(
                key,
                before ? 'BEFORE' : 'AFTER',
                pivot,
                JSON.stringify(value)
            );
        } catch (error) {
            console.error('Redis linsert error:', error);
            throw error;
        }
    },

    /**
     * 获取列表指定范围的元素
     * @param {string} key Redis键
     * @param {number} start 开始索引
     * @param {number} stop 结束索引
     */
    async lrange(key, start = 0, stop = -1) {
        try {
            const result = await redis.lrange(key, start, stop);
            return result.map(item => JSON.parse(item));
        } catch (error) {
            console.error('Redis lrange error:', error);
            throw error;
        }
    },

    /**
     * 获取列表长度
     * @param {string} key Redis键
     */
    async llen(key) {
        try {
            return await redis.llen(key);
        } catch (error) {
            console.error('Redis llen error:', error);
            throw error;
        }
    },

    /**
     * 使用有序集合实现排序
     * @param {string} key Redis键
     * @param {number} score 分数
     * @param {any} value 要插入的值
     */
    async zadd(key, score, value) {
        try {
            return await redis.zadd(key, score, JSON.stringify(value));
        } catch (error) {
            console.error('Redis zadd error:', error);
            throw error;
        }
    },

    /**
     * 获取有序集合的元素
     * @param {string} key Redis键
     * @param {number} start 开始索引
     * @param {number} stop 结束索引
     */
    async zrange(key, start = 0, stop = -1) {
        try {
            const result = await redis.zrange(key, start, stop);
            return result.map(item => JSON.parse(item));
        } catch (error) {
            console.error('Redis zrange error:', error);
            throw error;
        }
    },

    /**
     * 删除列表指定范围的元素
     * @param {string} key Redis键
     * @param {number} start 开始索引
     * @param {number} stop 结束索引
     */
    async ltrim(key, start = 0, stop = -1) {
        try {
            return await redis.del(key);
        } catch (error) {
            console.error('删除 Key 失败:', error);
            throw error;
        }
    },

    /**
     * 在列表中查找指定ID的数据
     * @param {string} listKey 列表的key
     * @param {string|number} targetId 要查找的ID
     * @returns {Promise<{data: any, index: number}|null>} 找到的数据和索引位置
     */
    async findInList(listKey, targetId) {
        try {
            // 获取列表长度
            const length = await redis.llen(listKey);
            if (length === 0) return null;

            // 分批获取数据以提高性能
            const batchSize = 100;

            for (let start = 0; start < length; start += batchSize) {
                const end = Math.min(start + batchSize - 1, length - 1);
                const items = await redis.lrange(listKey, start, end);

                for (let i = 0; i < items.length; i++) {
                    const item = JSON.parse(items[i]);
                    if (item.id == targetId) { // 使用 == 以处理字符串和数字的比较
                        return {
                            data: item,
                            index: start + i
                        };
                    }
                }
            }

            return null;
        } catch (error) {
            console.error('查找数据失败:', error);
            throw error;
        }
    },

    /**
     * 更新列表中指定位置的数据
     * @param {string} listKey 列表的key
     * @param {number} index 索引位置
     * @param {any} newData 新数据
     */
    async updateInList(listKey, index, newData) {
        try {
            await redis.lset(listKey, index, JSON.stringify(newData));
            return true;
        } catch (error) {
            console.error('更新数据失败:', error);
            throw error;
        }
    },

    /**
     * 删除列表中指定ID的数据
     * @param {string} listKey 列表的key
     * @param {string|number} targetId 要删除的ID
     */
    async removeFromList(listKey, targetId) {
        try {
            const found = await this.findInList(listKey, targetId);
            if (found) {
                // 使用 LSET 设置为标记值，然后用 LREM 删除
                await redis.lset(listKey, found.index, 'TO_DELETE');
                await redis.lrem(listKey, 1, 'TO_DELETE');
                return true;
            }
            return false;
        } catch (error) {
            console.error('删除数据失败:', error);
            throw error;
        }
    },
    /**
    * 获取指定前缀的所有key的数据
    * @param {string} prefix key前缀，如 'aimNoPushMsg'
    */
    async getListDataByPrefix(prefix) {
        try {
            // 1. 获取所有匹配的key
            const keys = await redis.keys(`${prefix}*`);
            if (!keys.length) return [];

            // 2. 获取每个key的所有数据
            const result = [];
            for (const key of keys) {
                const items = await redis.lrange(key, 0, -1);
                const parsedItems = items.map(item => {
                    try {
                        return JSON.parse(item);
                    } catch (e) {
                        return item;
                    }
                });
                result.push({
                    key,
                    data: parsedItems
                });
            }
            return result;
        } catch (error) {
            console.error('获取列表数据失败:', error);
            throw error;
        }
    },
};

module.exports = redisUtils;